package cn.exrick.xboot.modules.activiti.controller;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.jxls.area.Area;
import org.jxls.builder.AreaBuilder;
import org.jxls.builder.xml.XmlAreaBuilder;
import org.jxls.common.CellRef;
import org.jxls.common.Context;
import org.jxls.transform.Transformer;
import org.jxls.util.TransformerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.gson.Gson;

import cn.exrick.xboot.common.constant.ActivitiConstant;
import cn.exrick.xboot.common.constant.CommonConstant;
import cn.exrick.xboot.common.constant.SettingConstant;
import cn.exrick.xboot.common.exception.XbootException;
import cn.exrick.xboot.common.utils.CommonUtil;
import cn.exrick.xboot.common.utils.PageUtil;
import cn.exrick.xboot.common.utils.ResultUtil;
import cn.exrick.xboot.common.vo.PageVo;
import cn.exrick.xboot.common.vo.Result;
import cn.exrick.xboot.common.vo.SearchVo;
import cn.exrick.xboot.modules.activiti.entity.ActBusiness;
import cn.exrick.xboot.modules.activiti.entity.ActProcess;
import cn.exrick.xboot.modules.activiti.entity.business.ExportMatter;
import cn.exrick.xboot.modules.activiti.entity.business.Leave;
import cn.exrick.xboot.modules.activiti.service.ActBusinessService;
import cn.exrick.xboot.modules.activiti.service.ActProcessService;
import cn.exrick.xboot.modules.activiti.service.business.LeaveService;
import cn.exrick.xboot.modules.activiti.service.business.MatterAnalysisService;
import cn.exrick.xboot.modules.activiti.service.business.MatterService;
import cn.exrick.xboot.modules.activiti.service.mybatis.IActService;
import cn.exrick.xboot.modules.activiti.vo.ActBusiMatter;
import cn.exrick.xboot.modules.base.entity.Department;
import cn.exrick.xboot.modules.base.entity.Dict;
import cn.exrick.xboot.modules.base.entity.DictData;
import cn.exrick.xboot.modules.base.service.DepartmentService;
import cn.exrick.xboot.modules.base.service.DictDataService;
import cn.exrick.xboot.modules.base.service.DictService;
import cn.exrick.xboot.modules.base.service.SettingService;
import cn.exrick.xboot.modules.base.vo.OssSetting;
import cn.exrick.xboot.modules.file.entity.File;
import cn.exrick.xboot.modules.file.manage.FileManageFactory;
import cn.exrick.xboot.modules.file.service.FileService;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * @author Exrick
 */
@Slf4j
@RestController
@Api(description = "业务申请管理接口")
@RequestMapping("/xboot/actBusiness")
@Transactional
public class ActBusinessController {

	@Autowired
	private FileService fileService;
	
	@Autowired
	private SettingService settingService;
	
	@Autowired
	private FileManageFactory fileManageFactory;
	
    @Autowired
    private ActBusinessService actBusinessService;

    @Autowired
    private MatterAnalysisService matterAnalysisService;

    @Autowired
    private IActService iActService;

    @Autowired
    private MatterService matterService;

    @Autowired
    private ActProcessService actProcessService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private LeaveService leaveService;
    
    @Autowired
    private DictService dictService;
    
    @Autowired
    private DictDataService dictDataService;
    
    @Autowired
    private DepartmentService departmentService;

    @RequestMapping(value = "/getByCondition", method = RequestMethod.GET)
    @ApiOperation(value = "多条件分页获取申请列表")
    public Result<Page<ActBusiness>> getByCondition(@ModelAttribute ActBusiness actBusiness,
                                                    @ModelAttribute SearchVo searchVo,
                                                    @ModelAttribute PageVo pageVo){

        Page<ActBusiness> page = actBusinessService.findByCondition(actBusiness, searchVo, PageUtil.initPage(pageVo));
        page.getContent().forEach(e -> {
            if(StrUtil.isNotBlank(e.getProcDefId())){
                ActProcess actProcess = actProcessService.get(e.getProcDefId());
                e.setRouteName(actProcess.getRouteName());
                e.setProcessName(actProcess.getName());
            }
            if (e.getRouteName().equals("matter")){
                //12345
                e.setExtra(JSON.toJSONStringWithDateFormat(matterService.get(e.getTableId()),"yyyy-MM-dd HH:mm:ss"));
            }
            if(ActivitiConstant.STATUS_DEALING.equals(e.getStatus())){
                // 关联当前任务
                Task task = taskService.createTaskQuery().processInstanceId(e.getProcInstId()).list().get(0);
                if(task!=null){
                    e.setCurrTaskName(task.getName());
                }
            }
        });
        return new ResultUtil<Page<ActBusiness>>().setData(page);
    }

	@RequestMapping(value = "/exportByCondition")
	@ApiOperation(value = "多条件导出工单")
	public Result<Object> exportByCondition(@ModelAttribute ActBusiMatter actBusiness,
			@ModelAttribute SearchVo searchVo, @ModelAttribute PageVo pageVo) throws IOException {

		IPage<ActBusiMatter> page = matterAnalysisService.queryMatter(PageUtil.initMpPage(pageVo), searchVo, actBusiness);

		String result = generatorExcel(page.getRecords());
		return new ResultUtil<Object>().setData(result);
	}
    
    @RequestMapping(value = "/getByConditionV2", method = RequestMethod.GET)
    @ApiOperation(value = "多条件分页获取申请列表")
    public Result<IPage<ActBusiMatter>> getByConditionV2(@ModelAttribute ActBusiMatter actBusiness,
                                                         @ModelAttribute SearchVo searchVo,
                                                         @ModelAttribute PageVo pageVo){
        IPage<ActBusiMatter> page = matterAnalysisService.queryMatter(PageUtil.initMpPage(pageVo),searchVo,actBusiness);
        return new ResultUtil<IPage<ActBusiMatter>>().setData(page);
    }

    @RequestMapping(value = "/apply", method = RequestMethod.POST)
    @ApiOperation(value = "提交申请 启动流程")
    public Result<Object> apply(@ModelAttribute ActBusiness act){

        ActBusiness actBusiness = actBusinessService.get(act.getId());
        act.setTableId(actBusiness.getTableId());
        // 根据你的业务需求放入相应流程所需变量
        act = putParams(act);
        String processInstanceId = actProcessService.startProcess(act);
        actBusiness.setProcInstId(processInstanceId);
        actBusiness.setStatus(ActivitiConstant.STATUS_DEALING);
        actBusiness.setResult(ActivitiConstant.RESULT_DEALING);
        actBusiness.setApplyTime(new Date());
        actBusinessService.update(actBusiness);
        return new ResultUtil<Object>().setSuccessMsg("操作成功");
    }

    @RequestMapping(value = "/start", method = RequestMethod.POST)
    @ApiOperation(value = "流程选择组件启动流程")
    public Result<Object> start(@ModelAttribute ActBusiness act){

        ActBusiness actBusiness = actBusinessService.get(act.getId());
        act.setTableId(actBusiness.getTableId());
        // 根据你的业务需求放入相应流程所需变量
        act = putParams(act);
        String processInstanceId = actProcessService.startProcess(act);
        actBusiness.setProcDefId(act.getProcDefId());
        actBusiness.setTitle(act.getTitle());
        actBusiness.setProcInstId(processInstanceId);
        actBusiness.setStatus(ActivitiConstant.STATUS_DEALING);
        actBusiness.setResult(ActivitiConstant.RESULT_DEALING);
        actBusiness.setApplyTime(new Date());
        actBusinessService.update(actBusiness);
        return new ResultUtil<Object>().setSuccessMsg("操作成功");
    }

    /**
     * 放入相应流程所需变量
     * @param act
     * @return
     */
    public ActBusiness putParams(ActBusiness act){

        if(StrUtil.isBlank(act.getTableId())){
            throw new XbootException("关联业务表TableId不能为空");
        }
        // 如果属于请假流程
        Leave leave = leaveService.get(act.getTableId());
        if(leave!=null){
            // 放入变量
            act.getParams().put("duration", leave.getDuration());
        }
        return act;
    }

    @RequestMapping(value = "/cancel", method = RequestMethod.POST)
    @ApiOperation(value = "撤回申请")
    public Result<Object> cancel(@RequestParam String id,
                                 @RequestParam String procInstId,
                                 @RequestParam(required = false) String reason){

        if(StrUtil.isBlank(reason)){
            reason = "";
        }
        runtimeService.deleteProcessInstance(procInstId, "canceled-"+reason);
        ActBusiness actBusiness = actBusinessService.get(id);
        actBusiness.setStatus(ActivitiConstant.STATUS_CANCELED);
        actBusiness.setResult(ActivitiConstant.RESULT_TO_SUBMIT);
        actBusinessService.update(actBusiness);
        return new ResultUtil<Object>().setSuccessMsg("操作成功");
    }

    @RequestMapping(value = "/delByIds/{ids}", method = RequestMethod.DELETE)
    @ApiOperation(value = "通过id删除草稿状态申请")
    public Result<Object> delByIds(@PathVariable String[] ids){

        for(String id : ids){
            ActBusiness actBusiness = actBusinessService.get(id);
            if(!ActivitiConstant.STATUS_TO_APPLY.equals(actBusiness.getStatus())){
                return new ResultUtil<Object>().setErrorMsg("删除失败, 仅能删除草稿状态的申请");
            }
            // 删除关联业务表
            ActProcess actProcess = actProcessService.get(actBusiness.getProcDefId());
            iActService.deleteBusiness(actProcess.getBusinessTable(), actBusiness.getTableId());
            actBusinessService.delete(id);
        }
        return new ResultUtil<Object>().setSuccessMsg("删除成功");
    }

	private String generatorExcel(List<ActBusiMatter> records) throws IOException {
		List<ExportMatter> list = new ArrayList<ExportMatter>();

        List<Department> departmentList = departmentService.getAll();

        Dict dict = dictService.findByType("problem_type");
        List<DictData> dictDataList = new ArrayList<DictData>();
        if (dict != null) {
        	dictDataList = dictDataService.findByDictId(dict.getId());
        }
		int i = 1;
		for (ActBusiMatter record : records) {
			ExportMatter em = new ExportMatter();
			em.setXh(i);// 序号
			em.setRq("");// 日期 如：20日12时-21日12时
			String ssdw = "";
			for (Department department : departmentList) {
				if (department.getId().equals(record.getField0012())) {
					ssdw = department.getTitle();
				}
			}
			em.setSsdw(ssdw);// 所属单位
			em.setPdsj(DateUtil.format(record.getField0019(), "yyyy/MM/dd HH:mm"));// 派单时间 如：2019/10/20 13:11
			em.setGdbh(record.getField0001());// 工单编号 如：电[2019]A-45142238
			em.setLdr(record.getField0003());// 来电任 如：张先生
			em.setLxfs(record.getField0004());// 联系方式 如：13601062801
			String sqlx = "";
			for (DictData dictData : dictDataList) {
				if (dictData.getValue().equals(record.getField0007())) {
					sqlx = dictData.getTitle();
				}
			}
			System.out.println("查到诉求类型为：" + sqlx);
			em.setSqlx(sqlx);// 诉求类型 如：市政设施
			em.setSqdw(record.getField0006());// 诉求点位 如：南彩镇后俸伯西路大队部东侧
			em.setSqnr(record.getField0005());// 诉求内容 如：反映公厕不让使用问题
			em.setHfsj(DateUtil.format(record.getField0024(), "yyyy年MM月dd日"));// 回复时间 如：2019年10月20日
			em.setHfnr(record.getField0009());// 回复内容 如：南彩镇便民电话办公室工作人员于2019年10月20日14:00与反映人反馈，南彩镇后俸伯包村干部经过现场核实，反映人所反映的公共厕所每天都在正常开放使用，每天早七点到七点半保洁人员在清理厕所时会临时关闭，工作人员要求保洁人员每天加快清理厕所速度，缩短关门时间。工作将办理情况告知反映人后，并对反映人表示歉意，今后将避免问题再次发生，反映人对此处理结果表示满意。
			em.setJjqk(record.getField0034() == 0 ? "未解决" : record.getField0034() == 1 ? "解决" : "");// 解决情况 如：已解决/未解决
			em.setMyqk(record.getField0023() == 0 ? "不满意" : record.getField0023() == 1 ? "满意" : "");// 满意情况 如：满意/不满意
			em.setSpdw("");// 双派单位
			String ywks = "";
			for (Department department : departmentList) {
				if (department.getId().equals(record.getField0027())) {
					ywks = department.getTitle();
				}
			}
			em.setYwks(ywks);// 业务科室 如：便民电话专班
			em.setYwkslxfs("");// 业务科室联系方式 如：89471234
			list.add(em);
			i++;
		}
		String template = "template/MatterTemplate.xls";
		String templateConfig = "template/MatterConfig.xml";
		String fKey = CommonUtil.renamePic(".xls");
		String result = fileManageFactory.getFileManage(CommonConstant.OSS_LOCAL).pathUpload("", fKey);
		try (InputStream is = this.getClass().getResourceAsStream("/" + template)) {
			try (OutputStream os = new FileOutputStream(result)) {
				Transformer transformer = TransformerFactory.createTransformer(is, os);
				try (InputStream configInputStream = this.getClass().getResourceAsStream("/" + templateConfig)) {
					AreaBuilder areaBuilder = new XmlAreaBuilder(configInputStream, transformer);
					List<Area> xlsAreaList = areaBuilder.build();
					Area xlsArea = xlsAreaList.get(0);
					Context context = new Context();
					context.putVar("ExportMatter", list);
					xlsArea.applyAt(new CellRef("Result!A1"), context);
					transformer.write();
				}
			}
		}

		java.io.File file = new java.io.File(result);
		File f = new File();
		f.setLocation(CommonConstant.OSS_LOCAL);
		// 保存数据信息至数据库
		String day = DateUtil.format(DateUtil.date(), "yyyyMMdd");
		f.setName("双派单双考核诉求清单_" + day + ".xls");
		f.setSize(file.length());
		f.setFKey(fKey);
		f.setUrl(result);
		fileService.save(f);
		OssSetting os = new Gson().fromJson(settingService.get(SettingConstant.LOCAL_OSS).getValue(), OssSetting.class);
		result = os.getHttp() + os.getEndpoint() + "/" + f.getId() + "?byFilename=true";
		return result;
	}
}
